<!DOCTYPE html>
<html>
<!--
Copyright 2007 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by an Apache 2.0 License.
See the COPYING file for details.
-->
<!--
  Author: ajpalay@google.com (Andrew Palay)
-->
<head>
<title>Closure Unit Tests - goog.gears.ManagedResourceStore</title>
<script src="../base.js"></script>
<script>
  goog.require('goog.gears.ManagedResourceStore');
  goog.require('goog.testing.jsunit');
  goog.require('goog.testing.MockClock');
</script>
</head>
<body>
<script>

var clock;
var HAS_PROGRESS_EVENTS_VERSION = '0.3.6';
var shouldFail;


function setUp() {
  clock = new goog.testing.MockClock(true);
  shouldFail = false;
}


function tearDown() {
  clock.dispose();
}


// Create mocks


goog.gears.hasFactory = function() {
  return true;
};


var mockFactory = {
  create: function(classId) {
    if (classId == 'beta.timer') {
      // window implements the timer interface
      return window;
    } else if (classId == 'beta.localserver') {
      return mockLocalServer;
    }
  }
};


// Use this to change the mock gears factory as needed
function setGearsHasProgressEvents(gearsHasProgressEvents) {
  mockFactory.version = gearsHasProgressEvents ?
      HAS_PROGRESS_EVENTS_VERSION : '0.1';
}
setGearsHasProgressEvents(false);


goog.gears.getFactory = function() {
  return mockFactory;
};


var mockLocalServer = {
  openManagedStore: function(name, requiredCookie) {
    return new MockManagedResourceStore;
  },
  createManagedStore: function(name, requiredCookie) {
    return new MockManagedResourceStore;
  },
  removeManagedStore: function(name, requiredCookie) {

  }
};


function MockManagedResourceStore() {}


MockManagedResourceStore.prototype = {
  manifestUrl: '',
  currentVersion: '',
  updateStatus: 0,
  enabled: true,
  lastErrorMessage: '',
  checkForUpdate: function() {
    // Define some functions that will be used to trigger fake callbacks at
    // certain times
    var self = this;
    function setUpdateStatus(n, t) {
      window.setTimeout(function() {
        self.updateStatus = n;
      }, t);
    }
    function callOnProgress(complete, total, t) {
      window.setTimeout(function() {
        self.onprogress({filesComplete: complete, filesTotal: total});
      }, t);
    }
    function callOnComplete(version, t) {
      window.setTimeout(function() {
        self.oncomplete({newVersion: version});
      }, t);
    }
    function callOnError(message, t) {
      window.setTimeout(function() {
        self.lastErrorMessage = message;
        self.onerror({message: message});
      }, t);
    }

    var OK = goog.gears.ManagedResourceStore.UpdateStatus.OK;
    var CHECKING = goog.gears.ManagedResourceStore.UpdateStatus.CHECKING;
    var DOWNLOADING = goog.gears.ManagedResourceStore.UpdateStatus.DOWNLOADING;
    var FAILURE = goog.gears.ManagedResourceStore.UpdateStatus.FAILURE;

    this.updateStatus = CHECKING;

    if (goog.gears.getFactory().version == HAS_PROGRESS_EVENTS_VERSION) {
      callOnProgress(0, 0, 0);
      setUpdateStatus(DOWNLOADING, 1000);
      callOnProgress(0, 3, 1000);
      callOnProgress(1, 3, 2000);
      callOnProgress(2, 3, 2500);
      if (shouldFail) {
        setUpdateStatus(FAILURE, 3000);
        callOnError('ERROR', 3000);
      } else {
        callOnProgress(3, 3, 3000);
        setUpdateStatus(OK, 3000);
        callOnComplete('NEW_VERSION', 3000);
      }
    } else {
      // Use n * 1000 + 1 to make sure this happens just after a tick
      setUpdateStatus(DOWNLOADING, 1001);
      if (shouldFail) {
        self.lastErrorMessage = 'ERROR';
        setUpdateStatus(FAILURE, 2001);
      } else {
        setUpdateStatus(OK, 2001);
      }
    }

  }
};


// Start the real testing


var MANIFEST_NAME = 'testName';


function testManagedResourceStore() {
  var store = new goog.gears.ManagedResourceStore('tester',
      'managed-resource-store-test');
  store.create(MANIFEST_NAME);
  assertNotNull('No managed resource store object', store);
  assertTrue('Managed resource store not created', store.exists());
}


function testDoubleCreate() {
  var store = new goog.gears.ManagedResourceStore('tester',
      'managed-resource-store-test');
  store.create(MANIFEST_NAME);

  assertTrue('Managed resource store not created', store.exists());
  store.create(MANIFEST_NAME);
  assertTrue('Managed resource store no longer exists', store.exists());
}


function testUpdateOldSuccess() {
  setGearsHasProgressEvents(false);
  var progressCount = 0;
  var errorCount = 0;
  var completeCount = 0;
  var successCount = 0;
  var store = new goog.gears.ManagedResourceStore('tester',
      'managed-resource-store-test');

  store.create(MANIFEST_NAME);

  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.PROGRESS,
      function(e) {
        progressCount++;
        if (clock.getCurrentTime() == 0) {
          assertEquals('Should be 0 complete files',
                       0, store.getFilesComplete());
          assertEquals('Should be 1 total files',
                       1, store.getFilesTotal());
        }
        if (clock.getCurrentTime() == 2000) {
          assertEquals('Should be 1 complete files',
                       1, store.getFilesComplete());
          assertEquals('Should be 1 total files',
                       1, store.getFilesTotal());
        }
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.COMPLETE,
      function(e) {
        completeCount++;
        assertEquals('We should be complete at 2500ms', 2500,
                     clock.getCurrentTime());
        assertTrue('Should be successful', store.isSuccess());
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.ERROR,
      function(e) {
        errorCount++;
        assertEquals('ERROR', e.errorMessage);
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.SUCCESS,
      function(e) {
        successCount++;
      });

  store.update();

  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);

  assertEquals('Should have gotten 2 progress events', 2, progressCount);
  assertEquals('Should have gotten 1 complete events', 1, completeCount);
  assertEquals('Should have gotten 0 error events', 0, errorCount);
  assertEquals('Should have gotten 1 success events', 1, successCount);
}


function testUpdateOldFailure() {
  shouldFail = true;
  setGearsHasProgressEvents(false);
  var progressCount = 0;
  var errorCount = 0;
  var completeCount = 0;
  var successCount = 0;
  var store = new goog.gears.ManagedResourceStore('tester',
      'managed-resource-store-test');

  store.create(MANIFEST_NAME);

  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.PROGRESS,
      function(e) {
        progressCount++;
        if (clock.getCurrentTime() == 0) {
          assertEquals('Should be 0 complete files',
                       0, store.getFilesComplete());
          assertEquals('Should be 1 total files',
                       1, store.getFilesTotal());
        }
        if (clock.getCurrentTime() == 2000) {
          assertEquals('Should be 1 complete files',
                       1, store.getFilesComplete());
          assertEquals('Should be 1 total files',
                       1, store.getFilesTotal());
        }
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.COMPLETE,
      function(e) {
        completeCount++;
        assertEquals('We should be complete at 2500ms', 2500,
                     clock.getCurrentTime());
        assertFalse('Should not be successful', store.isSuccess());
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.ERROR,
      function(e) {
        errorCount++;
        assertEquals('ERROR', e.errorMessage);
      });

  store.update();

  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);

  assertEquals('Should have gotten 1 progress events', 1, progressCount);
  assertEquals('Should have gotten 1 complete events', 1, completeCount);
  assertEquals('Should have gotten 1 error events', 1, errorCount);
  assertEquals('Should have gotten 0 success events', 0, successCount);
}


function testUpdateNewSuccess() {
  setGearsHasProgressEvents(true);
  var progressCount = 0;
  var errorCount = 0;
  var completeCount = 0;
  var successCount = 0;
  var store = new goog.gears.ManagedResourceStore('tester',
      'managed-resource-store-test');

  store.create(MANIFEST_NAME);

  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.PROGRESS,
      function(e) {
        progressCount++;
        if (clock.getCurrentTime() == 0) {
          assertEquals('Should be 1 total files',
                       1, store.getFilesTotal());
          assertEquals('Should be 0 complete files',
                       0, store.getFilesComplete());
        } else {
          assertEquals('Should be 3 total files',
                       3, store.getFilesTotal());
        }

        if (clock.getCurrentTime() == 2000) {
          assertEquals('Should be 1 complete files',
                       1, store.getFilesComplete());
        } else if (clock.getCurrentTime() == 2500) {
          assertEquals('Should be 2 complete files',
                       2, store.getFilesComplete());
        } else if (clock.getCurrentTime() == 3000) {
          assertEquals('Should be 2 complete files',
                       3, store.getFilesComplete());
        }
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.COMPLETE,
      function(e) {
        completeCount++;
        assertEquals('We should be complete at 3000ms', 3000,
                     clock.getCurrentTime());
        assertTrue('Should be successful', store.isSuccess());
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.ERROR,
      function(e) {
        errorCount++;
        assertEquals('ERROR', e.errorMessage);
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.SUCCESS,
      function(e) {
        assertEquals('success at 3000ms', 3000,
                     clock.getCurrentTime());
        successCount++;
      });

  store.update();

  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);

  // Starts at 0/0 so we don't get progress for that
  // 0/3, 1/3, 2/3, 3/3
  assertEquals('Should have gotten 4 progress events', 4, progressCount);
  assertEquals('Should have gotten 1 complete events', 1, completeCount);
  assertEquals('Should have gotten 0 error events', 0, errorCount);
  assertEquals('Should have gotten 1 success events', 1, successCount);
}


function testUpdateNewFailure() {
  shouldFail = true;
  setGearsHasProgressEvents(true);
  var progressCount = 0;
  var errorCount = 0;
  var completeCount = 0;
  var successCount = 0;
  var store = new goog.gears.ManagedResourceStore('tester',
      'managed-resource-store-test');

  store.create(MANIFEST_NAME);

  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.PROGRESS,
      function(e) {
        progressCount++;
        if (clock.getCurrentTime() == 0) {
          assertEquals('Should be 1 total files',
                       1, store.getFilesTotal());
          assertEquals('Should be 0 complete files',
                       0, store.getFilesComplete());
        } else {
          assertEquals('Should be 3 total files',
                       3, store.getFilesTotal());
        }

        if (clock.getCurrentTime() == 2000) {
          assertEquals('Should be 1 complete files',
                       1, store.getFilesComplete());
        } else if (clock.getCurrentTime() == 2500) {
          assertEquals('Should be 2 complete files',
                       2, store.getFilesComplete());
        } else if (clock.getCurrentTime() == 3000) {
          assertEquals('Should be 2 complete files',
                       3, store.getFilesComplete());
        }
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.COMPLETE,
      function(e) {
        completeCount++;
        assertEquals('We should be complete at 3000ms', 3000,
                     clock.getCurrentTime());
        assertFalse('Should not be successful', store.isSuccess());
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.ERROR,
      function(e) {
        errorCount++;
        assertEquals('ERROR', e.errorMessage);
      });
  goog.events.listen(store, goog.gears.ManagedResourceStore.EventType.SUCCESS,
      function(e) {
        assertEquals('success at 3000ms', 3000,
                     clock.getCurrentTime());
        successCount++;
      });

  store.update();

  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);
  clock.tick(500);

  // When we fail we don't get the third file

  // Starts at 0/0 so we don't get progress for that
  // 0/3, 1/3, 2/3
  assertEquals('Should have gotten 3 progress events', 3, progressCount);
  assertEquals('Should have gotten 1 complete events', 1, completeCount);
  assertEquals('Should have gotten 1 error events', 1, errorCount);
  assertEquals('Should have gotten 0 success events', 0, successCount);
}


</script>
</body>
</html>
